package com.program.facesigninsystem.controller;

import cn.yueshutong.springbootstartercurrentlimiting.annotation.CurrentLimiter;
import com.program.facesigninsystem.entity.*;
import com.program.facesigninsystem.service.*;
import com.program.facesigninsystem.service.impl.WebSocketServer;
import com.program.facesigninsystem.util.*;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Mapler
 */
@CrossOrigin
@RestController
@RequestMapping(value = "/rec")
public class SignInRecordController {
    private static Logger log = Logger.getLogger(SignInRecordController.class.toString());
    @Autowired
    ISignInRecordService iSignInRecordService;
    @Autowired
    ISignInActivityService iSignInActivityService;
    @Autowired
    IRewardService iRewardService;
    @Autowired
    ISignInTypeService iSignInTypeService;
    @Autowired
    public IUserInfoService iUserService;
    @Autowired
    public IUserClassService iUserClassService;
    @Autowired
    public IClassesService iClassesService;

    @RequestMapping(value = "/resultTeacher", method = RequestMethod.GET)
    @CurrentLimiter(QPS=5)
    public ResponseModel resultTeacher(@RequestParam("lid") String lid) {
        ResponseModel responseModel;
        try {
            List<Map<String, Object>> recordList = iSignInRecordService.selectRecordList(lid);
            for (Map<String, Object> map : recordList) {
                Object value = map.get("signintime");
                ChangeDate changeDate = new ChangeDate();
                changeDate.setSettime(value.toString());
                map.put("signintime", changeDate.getSettime());
                map.putIfAbsent("state", "");
            }
            SignInActivity signInActivity = iSignInActivityService.selectAct(lid);
            String title = signInActivity.getTitle();
            int count = iSignInRecordService.selectRecCount(lid);
            ArrayList<Object> data = new ArrayList<>();
            data.add(0, title);
            Map<String, Object> map = new HashMap<>(1);
            map.put("已签到", count);
            data.add(1, map);
            data.add(recordList);
            responseModel = new ResponseModel(200, "获取成功", data);
        } catch (Exception e) {
            responseModel = new ResponseModel(199, "获取失败");
        }
        return responseModel;
    }

    @RequestMapping(value = "/noSignInTea", method = RequestMethod.GET)
    @CurrentLimiter(QPS=5)
    public ResponseModel noSignInTea(@RequestParam("lid") String lid) {
        SignInActivity signInActivity = iSignInActivityService.selectAct(lid);
        String cid = signInActivity.getCid();
        ResponseModel responseModel;
        if (!"".equals(cid)){
            Classes classes = iClassesService.selectClass(cid);
            if(classes == null) {
                return new ResponseModel(198, "名单中无成员");
            }
            if (classes.getR_count() != 0) {
                try {
                    List<Map<String, Object>> userList = iSignInRecordService.selectNoSignIn(cid, lid);
                    String title = signInActivity.getTitle();
                    int count = classes.getR_count() - iSignInRecordService.selectRecCount(lid);
                    ArrayList<Object> data = new ArrayList<>();
                    data.add(0, title);
                    Map<String, Object> map = new HashMap<>(1);
                    map.put("未签到", count);
                    data.add(1, map);
                    data.add(userList);
                    responseModel = new ResponseModel(200, "获取成功", data);
                } catch (Exception e) {
                    responseModel = new ResponseModel(199, "获取失败");
                }
            } else {
                responseModel = new ResponseModel(198, "名单中无成员");
            }
        }else{
            responseModel = new ResponseModel(197,"无名单");
        }
        return responseModel;
    }

    @RequestMapping(value = "/addNewRecord", method = RequestMethod.GET)
    @CurrentLimiter(QPS=10)
    public ResponseModel addNewRecord(
            @RequestParam("lid") String lid,
            @RequestParam("uid") String uid,
            @RequestParam("location_x") double locationX,
            @RequestParam("location_y") double locationY,
            @RequestParam(value = "state",required = false,defaultValue = "normal")String state) {
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String id = GetInfoUtil.getId();
            SignInActivity signInActivity = iSignInActivityService.selectAct(lid);
            String tid = signInActivity.getTid();
            Rewards rewards = iRewardService.selectReward(uid);
            Rewards rewardsTeacher = iRewardService.selectReward(tid);
            String cid = signInActivity.getCid();
            UserClass userClass = null;
            Map<String,Object> map = iUserService.selectUser(uid);
            String userName = map.get("name")==null?"":map.get("name").toString();
            String avatar = map.get("avatar")==null?"":map.get("avatar").toString();
            if (!"".equals(cid)) {
                userClass = iUserClassService.selectUserClass(uid, cid);
            }
            if ("".equals(cid) || userClass != null) {
                SignInRecord signInRecord = iSignInRecordService.selectRecExist(uid, lid);
                if (signInRecord == null) {
                    SignInLink signInLink = iSignInActivityService.selectLinkByLid(lid);
                    ChangeDate changeDate = new ChangeDate();
                    changeDate.setSettime(signInLink.getEndTime());
                    Date date = new Date(System.currentTimeMillis());
                    String createTime = dateFormat.format(System.currentTimeMillis());
                    if (!date.before(changeDate.settime)) {
                        WebSocketServer.sendMessage("{\"name\":\""+userName+"\",\"avatar\":\""+avatar+"\",\"lid\":\""+lid+"\"}",tid);
                        iSignInRecordService.signinByTea(id, uid, lid, createTime,"迟到");
                        return new ResponseModel(200, "签到成功，已迟到");
                    }
                    if (signInLink.getLocation_x() != 0 && signInLink.getLocation_y() != 0 && signInLink.getRangement() != 0) {
                        if (locationX != 0 && locationY != 0) {
                            double distance = LocationUtil.algorithm(signInLink.getLocation_x(), signInLink.getLocation_y(), locationX, locationY);
                            if (distance > signInLink.getRangement()) {
                                return new ResponseModel(165, "签到失败,未在签到范围内");
                            }
                        } else {
                            return new ResponseModel(164, "签到失败,未传坐标");
                        }
                    }
                    iSignInRecordService.addNewRecord(id, lid, uid, createTime,state);
                    String currentDay = dateFormat.format(System.currentTimeMillis()).substring(0, 10);
                    WebSocketServer.sendMessage("{\"name\":\""+userName+"\",\"avatar\":\""+avatar+"\",\"lid\":\""+lid+"\"}",tid);
                    return addReward(rewardsTeacher,rewards,uid,currentDay,tid);
                } else {
                    return new ResponseModel(198, "您已签到");
                }
            } else {
                return new ResponseModel(199, "您未在签到名单中");
            }
        } catch (Exception e) {
            log.log(Level.SEVERE,"Error parsing date",e);
            return new ResponseModel(169, "签到失败");
        }
    }

    @RequestMapping(value = "/recByTea", method = RequestMethod.GET)
    public ResponseModel addRecByTea(@RequestParam("uid") String uid, @RequestParam("lid") String lid,@RequestParam("state") String state) {
        try {
                String id = GetInfoUtil.getId();
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String createTime = dateFormat.format(System.currentTimeMillis());
                iSignInRecordService.signinByTea(id, uid, lid, createTime, state);
                return new ResponseModel(200, "代签成功");
        } catch (Exception e) {
            log.log(Level.SEVERE,"Error parsing date",e);
            return new ResponseModel(169, "代签失败");
        }
    }

    @RequestMapping(value = "/selectRecord", method = RequestMethod.GET)
    @CurrentLimiter(QPS=5)
    public ResponseModel selectRecord(@RequestParam(value = "date", required = false) String date, @RequestParam("uid") String uid) {
        try {
            List<SignInRecord> signInRecordList;
            Object[] objects;
            if (date == null) {
                signInRecordList = iSignInRecordService.selectRecordAll(uid);
                objects = signInRecordList.toArray();
            } else {
                String date1 = date + " 00:00:00";
                String date2 = date + " 23:59:59";
                signInRecordList = iSignInRecordService.selectRecord(uid, date1, date2);
                objects = signInRecordList.toArray();
            }
            return new ResponseModel(200, "获取成功", objects);
        } catch (Exception e) {
            log.log(Level.SEVERE,"Error parsing date",e);
            return new ResponseModel(168, "获取失败");
        }
    }

    @RequestMapping(value = "/selectRecordByMonth", method = RequestMethod.GET)
    public ResponseModel selectRecordByMonth(@RequestParam("uid") String uid, @RequestParam("month") String month) {
        try {
            List<Integer> outDays = new ArrayList<>();
            List<SignInRecord> days = iSignInRecordService.selectRecordByMonth(uid, month);
            System.out.println(days);
            Iterator iterator = days.iterator();
            int day;
            SignInRecord signInRecord;
            while (iterator.hasNext()) {
                signInRecord = (SignInRecord) iterator.next();
                day = Integer.parseInt(signInRecord.getSignintime().toString().substring(8, 10));
                if (!outDays.contains(day)) {
                    outDays.add(day);
                }
            }
            return new ResponseModel(200, "获取成功", outDays);
        } catch (Exception e) {
            log.log(Level.SEVERE,"Error parsing date",e);
            return new ResponseModel(139, "获取失败");
        }
    }

    @RequestMapping(value = "/selectRank", method = RequestMethod.GET)
    public ResponseModel selectRank() {
        try {
            return new ResponseModel(200, "获取成功", iSignInRecordService.selectRank());
        } catch (Exception e) {
            return new ResponseModel(129, "获取失败");
        }
    }

    @RequestMapping(value = "/selectMyRecord", method = RequestMethod.GET)
    @CurrentLimiter(QPS=5)
    public ResponseModel selectMyRecord(@RequestParam("uid") String uid, @RequestParam("date") String date) {
        try {
            return new ResponseModel(200, "获取成功", iSignInRecordService.selectMyRecord(uid, date));
        } catch (Exception e) {
            return new ResponseModel(128, "获取失败");
        }
    }

    @RequestMapping(value = "/selectList", method = RequestMethod.GET)
    public void selectList(HttpServletResponse resp, @RequestParam(value = "lid") String lid,
                            @RequestParam(value = "pageNum", required = false, defaultValue = "1") int pageNum,
                            @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize) {
        try {
            List<Map<String, Object>> mapList = iSignInRecordService.selectList(lid);
            try {
                JSONObject jsonObject = PageUtil.wrap2(mapList,"Record",pageSize,pageNum);
                /*设置编码，防止出现乱码问题*/
                resp.setCharacterEncoding("utf-8");
                /*得到输出流*/
                PrintWriter respWriter = resp.getWriter();
                /*将JSON格式的对象toString()后发送*/
                respWriter.append(jsonObject.toString());
            } catch (Exception e) {
                log.log(Level.SEVERE,"Error parsing date",e);
            }
        } catch (Exception e) {
            log.log(Level.SEVERE,"Error parsing date",e);
        }
    }

    @RequestMapping(value = "/excel", method = RequestMethod.GET)
    @CurrentLimiter(QPS=5)
    public void exportCorpLoanDemand(@RequestParam("lid")String lid, HttpServletRequest request, HttpServletResponse response) {
        try {
            SignInActivity signInActivity=iSignInActivityService.selectAct(lid);
            String actTitle=signInActivity.getTitle();
            String linkName=iSignInTypeService.selectName(lid);
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String time = dateFormat.format(System.currentTimeMillis());
            String fileName=actTitle+"+"+linkName+"+"+time+".xls";
            iSignInRecordService.exportExcel(fileName,lid,request,response);
        }catch (Exception e){
            log.log(Level.SEVERE,"Error parsing date",e);
        }
    }

    private ResponseModel addReward(Rewards rewardsTeacher, Rewards rewards, String uid, String currentDay, String tid){
        String lastGainDay;
        int a = rewardsTeacher.getLimit_from_record_a();
        int b = rewardsTeacher.getLimit_from_record_b();
        int c = rewardsTeacher.getLimit_from_record_c();
        int activity = rewardsTeacher.getLimit_from_activity();
        //学生签到成功，教师加2分
        int dayMaxRewards = 100;
        if (rewardsTeacher.getDay_reward() < dayMaxRewards) {
            int rewardPerTimeForTea = 2;
            iRewardService.updateRewards(tid, a, b, c, activity, currentDay,
                    rewardsTeacher.getReward_points() + rewardPerTimeForTea,
                    rewardsTeacher.getDay_reward() + rewardPerTimeForTea
            );
        }
        //有则更新记录
        int rewardPerTime = 30;
        if(rewards != null) {
            int limitFromRecordActivity = rewards.getLimit_from_activity();
            lastGainDay = rewards.getLast_gain_day();
            int rewardPoint = rewards.getReward_points();
            if (!lastGainDay.equals(currentDay)) {
                //如果上次获取积分的日期不等于今天，则直接加上积分，并将上次获取积分的日期改为今天
                iRewardService.updateRewards(uid, 1, 0, 0,
                        0, currentDay, rewardPoint + rewardPerTime, rewardPerTime);
                return new ResponseModel(200, "签到成功", "积分 +30");
            }
            //如果今日获取积分已达上限
            if (dayMaxRewards < rewards.getDay_reward()) {
                return new ResponseModel(200, "签到成功", "今日获取总积分已达上限");
            }
            //判断是不是今天第一次获取
            else if (rewards.getLimit_from_record_a() == 0) {
                iRewardService.updateRewards(
                        uid, 1, 0, 0, limitFromRecordActivity, currentDay,
                        rewardPoint + rewardPerTime, rewards.getDay_reward() + rewardPerTime);
            }
            //判断是不是今天第二次获取
            else if (rewards.getLimit_from_record_b() == 0) {
                iRewardService.updateRewards(
                        uid, 1, 1, 0, limitFromRecordActivity, currentDay,
                        rewardPoint + rewardPerTime, rewards.getDay_reward() + rewardPerTime);
            }
            //判断是不是今天第三次获取
            else if (rewards.getLimit_from_record_c() == 0) {
                iRewardService.updateRewards(
                        uid, 1, 1, 1, limitFromRecordActivity, currentDay,
                        rewardPoint + rewardPerTime, rewards.getDay_reward() + rewardPerTime
                );
            } else {
                return new ResponseModel(200, "签到成功", "今日签到获取积分次数已达上限");
            }
            return new ResponseModel(200, "签到成功", "积分 +30");
        }
        //无记录新增积分记录
        iRewardService.addNewRewards(uid, 1, 0, 0, 0,
                currentDay, rewardPerTime, rewardPerTime
        );
        return new ResponseModel(200, "签到成功", "积分 +30");
    }

    /***
     * 对比名单
     * @return ResponseModel
     */
    @RequestMapping(value = "/contrast",method = RequestMethod.GET)
    public  ResponseModel contrast(@RequestParam("filePath")String filePath,@RequestParam("lid")String lid) {
        File file=new File(filePath);
        int lastIndexOf=filePath.lastIndexOf(".");
        String suffix=filePath.substring(lastIndexOf+1);
        if(!file.exists()){
            return new ResponseModel(198,"名单不存在");
        }else {
            try {
                List<Map<String, Object>> recordList = iSignInRecordService.selectRecordList(lid);
                List<String> namelist=new ArrayList<>();
                List<Map<String,String>> noSignin=new ArrayList<>();
                List excelList;
                switch (suffix) {
                    case "xls":
                        excelList = ExcelUtil.readXls(file);
                        break;
                    case "xlsx":
                        excelList = ExcelUtil.readXlsx(file);
                        break;
                    default:
                        return new ResponseModel(197, "文件格式不支持");
                }
                if(excelList==null){
                    return new ResponseModel(190, "文件第一行不存在关键字“姓名”");
                }
                for (Map<String, Object> map : recordList) {
                    Object value = map.get("name");
                    namelist.add(value.toString());
                }
                for (Object anExcelList : excelList) {
                    List list = (List) anExcelList;
                    for (Object aList : list) {
                        boolean f = namelist.contains(aList.toString());
                        if (!f) {
                            Map<String,String> unSign = new HashMap<>(1);
                            unSign.put("name",aList.toString());
                            noSignin.add(unSign);
                        }
                    }
                }
                return new ResponseModel(200,"对比成功",noSignin);
            } catch (Exception e) {
                return new ResponseModel(199, "对比失败");
            }
        }
    }

    @RequestMapping(value = "/selectDistinctState",method = RequestMethod.GET)
    public  ResponseModel selectDistinctState(@RequestParam("lid")String lid) {
        return iSignInRecordService.selectDistinctState(lid);
    }

    @RequestMapping(value = "/setSignInState",method = RequestMethod.GET)
    public  ResponseModel setSignInState(@RequestParam("uid")String uid,@RequestParam("state")String state,@RequestParam("lid")String lid) {
        return iSignInRecordService.setSignInState(uid, lid,state);
    }

}
